package uit.nfcmenu.webservice;

import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import uit.nfcmenu.db.model.ItemModel;
import uit.nfcmenu.db.model.MenuModel;
import uit.nfcmenu.db.model.OrderModel;
import uit.nfcmenu.util.CommConstant;
import uit.nfcmenu.util.ConvertImg;
import uit.nfcmenu.util.ImageHelper;
import uit.nfcmenu.util.Utilities;
import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;


public class JSONParser {
	public static final String tag = JSONParser.class.getSimpleName();
	
	// TODO Keyword to parse objects >
//	private static String KEY_MENU = "menu";
//	private static String KEY_MENU_ID = "menuID";
//	private static String KEY_MENU_NAME = "menuName";
//	
//	private static String KEY_ITEM = "item";
//	private static String KEY_ITEM_ID = "itemID";
//	private static String KEY_ITEM_NAME = "itemName";
//	
//	private static String KEY_IMAGE = "image";
//	private static String KEY_IMAGE_LINK = "imageLink";
//	private static String KEY_DISCOUNT = "disCount";
//	private static String KEY_PRICE = "price";
//	private static String KEY_DESCRIPTION_EN = "description";
//	private static String KEY_DESCRIPTION_VI = "description_vn";
//	private static String KEY_DESCRIPTION_JA = "description_ja";
//	
//	private static String KEY_ORDER = "order";
//	private static String KEY_ORDER_ID = "orderID";
//	private static String KEY_ORDER_TIME = "orderTime";
//	
//	private static String KEY_QUANTITY = "quantity";
//	private static String KEY_STATUS = "status";
//	private static String KEY_TABLE_NO = "tableNo";
//	private static String KEY_COMMENT = "comment";
	
	//{"CompanyID":0,"CompanyName":null,"DevideName":"","UserToken":""}
	private static final String KEY_COMPANY_ID = "CompanyID";
	private static final String KEY_COMPANY_NAME = "CompanyName";
	private static final String KEY_DEVICE_NAME = "DevideName";
	private static final String KEY_USER_TOKEN = "UserToken";
	
	// {CompanyID: 2, ItemVersion: 0, MenuVersion: 0, OrderVersion: 1 }
	private static final String KEY_VERSION_MENU = "MenuVersion";
	private static final String KEY_VERSION_ITEM = "ItemVersion";
	private static final String KEY_VERSION_ORDER = "OrderVersion";
	
	private static final String KEY = "results";
	private static final String KEY_ID = "ID";
	private static final String KEY_MENU_ID = "MenuID";
	private static final String KEY_ITEM_ID = "ItemID";
	
	private static final String KEY_NAME_EN = "NameEN";
	private static final String KEY_NAME_JA = "NameJA";
	private static final String KEY_NAME_VI = "NameVN";
	private static final String KEY_DESCRIPTION_EN = "DescriptionEN";
	private static final String KEY_DESCRIPTION_JA = "DescriptionJA";
	private static final String KEY_DESCRIPTION_VI = "DescriptionVN";
	
	private static final String KEY_IMAGE_LINK = "ImageLink";
	private static final String KEY_DISCOUNT = "Discount";
	private static final String KEY_PRICE = "Price";
	private static final String KEY_MONEY_TYPE = "MoneyType";
	
	private static final String KEY_ORDER_TIME = "OrderTime";
	private static final String KEY_ORDER_USER = "OrderUser";	
	private static final String KEY_QUANTITY = "Quantity";
	private static final String KEY_STATUS = "Status";
	private static final String KEY_TABLE_NO = "TableNo";
	private static final String KEY_COMMENT = "Comment";
	
	// Keyword to parse objects />

	private static final String splitSign = "#.#";
	
	private static int EN_INDEX = 0;
	private static int JA_INDEX = 1;
	private static int VI_INDEX = 2;

	/*
	 * Define order of language
	 * 	ENGLISH, JAPENESE, VIETNAMESE 
	 */
	public static String getStringByLanguage(String info, String language) {
		//Log.i(tag, "getStringByLanguage("+string+","+language+")");
		if (info == null || "".equals(info.trim())) {
			return "";
		}
		String result = "";
		String[] strings = info.split(splitSign);
		if (strings != null && strings.length > 0) {
			result = strings[EN_INDEX]; // Locale.ENGLISH.toString().equals(language)
			if (strings != null && strings.length >= 3) { 
				if (Locale.JAPANESE.toString().equals(language)) {
					result = strings[JA_INDEX];
				} else if (CommConstant.LANGUAGE_VI.equals(language)){
					result = strings[VI_INDEX];
				}
			}
		}

		//Log.i(tag, "getStringByLanguage() return " + result);
		return result;
	}

	private static String getMergeServerStrings(String stringEn, String stringJa, String stringVi) {
		return stringEn + splitSign + stringJa + splitSign + stringVi;
	}
	
	// ========================================
	// Parser methods
	// ========================================

	/* {
			CompanyID: 2,
			ItemVersion: 0,
			MenuVersion: 0,
			OrderVersion: 1
		}
	 */
	public static int parseNotify(Context context, String response, int type) {
		if (response != null) {
			JSONObject jo = null;
			try {
				jo = new JSONObject(response);
				String keyVersion = "";
				switch (type) {
				case CommConstant.CHANGED_MENU:
					keyVersion = KEY_VERSION_MENU;
					break;
				case CommConstant.CHANGED_ITEM:
					keyVersion = KEY_VERSION_ITEM;
					break;
				case CommConstant.CHANGED_ORDER:
					keyVersion = KEY_VERSION_ORDER;
					break;
				}
				int version = jo.getInt(keyVersion);
				return version;
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		return 0;
	}
	
	public static UserModel parseUser(String response) {
		UserModel model = null;
		if (response != null) {
			try {
				JSONObject jo = new JSONObject(response);
				model = createUserModel(jo);
			} catch (JSONException e) {
				e.printStackTrace();
			}
		}
		
		return model;
	}

	public static ArrayList<MenuModel> parseMenus(String response) { 
		ArrayList<MenuModel> models = new ArrayList<MenuModel>();
		if (response != null) {
			JSONObject jo = null;
			JSONArray ja = null;
			MenuModel model = null;
			JSONObject joTemp = null;
			try {
				jo = new JSONObject(response);
				ja = jo.getJSONArray(KEY);

				int len = ja.length();
				for (int i = 0; i < len; i++) {
					joTemp = ja.getJSONObject(i);
					model = createMenuModel(joTemp);
					models.add(model);
					// Log.i(tag, "get "+model.toString());
				}

			} catch (JSONException e) {
				e.printStackTrace();
				if (ja == null && jo != null) {
					try {
						joTemp = jo.getJSONObject(KEY);
						model = createMenuModel(joTemp);
						models.add(model);
					} catch (JSONException e1) {
						e1.printStackTrace();
					}
				}
			}
		}

		return models;
	}

	public static ArrayList<ItemModel> parseItems(String response) {
		ArrayList<ItemModel> models = null;
		models = new ArrayList<ItemModel>();
		if (response != null) {
			JSONObject jo = null;
			JSONArray ja = null;
			JSONObject joTemp = null;
			ItemModel model = null;
			try {
				jo = new JSONObject(response);
				ja = jo.getJSONArray(KEY);
				
				if (ja != null) {
					int len = ja.length();
					for (int i = 0; i < len; i++) {
						joTemp = ja.getJSONObject(i);
						model = creatItemModel(joTemp);
						models.add(model);
					}
				}
			} catch (JSONException e) {
				if (ja == null && jo != null) {
					try {
						joTemp = jo.getJSONObject(KEY);
						model = creatItemModel(joTemp);
						models.add(model);
					} catch (JSONException e1) {
						e1.printStackTrace();
					}
				}
			}
		}

		return models;
	}


	/**
	 * Parse data to get Order Such as from json: { orders: [ { itemID: "1",
	 * orderID: "16002", orderTime: "Thu Feb 23 15:12:06 UTC 2012", quantity:
	 * "1", status: "cooking", tableNo: "5" }, ...
	 * 
	 * @param response
	 * @return
	 */

	public static ArrayList<OrderModel> parseOrders(String response) {
		ArrayList<OrderModel> models = new ArrayList<OrderModel>();
		if (response != null) {
			JSONObject jo = null;
			JSONArray ja = null;
			JSONObject joTemp = null;
			OrderModel model = null;
			try {
				jo = new JSONObject(response);
				ja = jo.getJSONArray(KEY);

				int len = ja.length();
				for (int i = 0; i < len; i++) {
					joTemp = ja.getJSONObject(i);	
					model = createOrderModel(joTemp);
					models.add(model);
				}
			} catch (JSONException e) {
				if (ja == null && jo != null) {
					try {
						joTemp = jo.getJSONObject(KEY);
						model = createOrderModel(joTemp);
						models.add(model);
					} catch (JSONException e1) {
						e1.printStackTrace();
					}
				}
			}
		}

		return models;
	}

	// ========================================
	// Creator methods
	// ========================================
	
	//{"CompanyID":0,"CompanyName":null,"DevideName":"","UserToken":""}
	private static UserModel createUserModel(JSONObject jo) throws JSONException {
		UserModel model = new UserModel();
		model.setCompanyId(jo.getString(KEY_COMPANY_ID));
		model.setCompanyName(jo.getString(KEY_COMPANY_NAME));
		model.setDeviceName(jo.getString(KEY_DEVICE_NAME));
		model.setUserToken(jo.getString(KEY_USER_TOKEN));
		Log.i(tag, "get user: " + model.toString());
		return model;
	}

	private static MenuModel createMenuModel(JSONObject joTemp)
			throws JSONException {
		MenuModel model = new MenuModel();
		
		model.setId(joTemp.getInt(KEY_ID));
		
		// TODO ttnlan: func change language >
		String nameEn = joTemp.getString(KEY_NAME_EN);
		String nameJa = joTemp.getString(KEY_NAME_JA);
		String nameVi = joTemp.getString(KEY_NAME_VI);
		String name = getMergeServerStrings(nameEn, nameJa, nameVi);
		model.setName(name);

		String desEn = joTemp.getString(KEY_DESCRIPTION_EN);
		String desJa = joTemp.getString(KEY_DESCRIPTION_JA);
		String desVi = joTemp.getString(KEY_DESCRIPTION_VI);
		String des = getMergeServerStrings(desEn, desJa, desVi);
		model.setDescription(des);
		// />
		
		// TODO ttnlan: fix lack refix server in some server link >
		String imgLink = CommonWS.getLinkIfLack(joTemp.getString(KEY_IMAGE_LINK));
		model.setImageLink(imgLink);
		// />
		
		// TODO ttnlan: download image bitmap > 
		byte[] imgBytes = ImageHelper.downloadFileFromUrl(imgLink);
		Bitmap bitmap = ConvertImg.getBitmap(imgBytes);
		model.setBitmap(bitmap);
		// />
		
		//Log.i(tag, "get menu: " + model.toString());
		return model;
	}

	private static ItemModel creatItemModel(JSONObject joTemp)
			throws JSONException {
		ItemModel model = new ItemModel();
		
		model.setId(joTemp.getInt(KEY_ID));
		model.setMenuId(joTemp.getInt(KEY_MENU_ID));
		model.setDiscount(joTemp.getInt(KEY_DISCOUNT));
		model.setPrice(Integer.parseInt(joTemp.getString(KEY_PRICE)));
		model.setMoneyType(joTemp.getString(KEY_MONEY_TYPE).trim());
		
		// TODO ttnlan: func change language >
		String nameEn = joTemp.getString(KEY_NAME_EN);
		String nameJa = joTemp.getString(KEY_NAME_JA);
		String nameVi = joTemp.getString(KEY_NAME_VI);
		String name = getMergeServerStrings(nameEn, nameJa, nameVi);
		model.setName(name);
		
		String desEn = joTemp.getString(KEY_DESCRIPTION_EN);
		String desJa = joTemp.getString(KEY_DESCRIPTION_JA);
		String desVi = joTemp.getString(KEY_DESCRIPTION_VI);
		String des = getMergeServerStrings(desEn, desJa, desVi);
		model.setDescription(des);
		// />

		// TODO ttnlan: fix lack refix server in some server link
		String imgLink = CommonWS.getLinkIfLack(joTemp.getString(KEY_IMAGE_LINK));
//		Log.e(tag, "creatItemModel() imgLink="+imgLink);
		model.setImageLink(imgLink);
		// />
		
		// TODO ttnlan: download image bitmap > 
		byte[] imgBytes = ImageHelper.downloadFileFromUrl(imgLink);
		Bitmap bitmap = ConvertImg.getBitmap(imgBytes);
		model.setBitmap(bitmap);
		// />

		//Log.i(tag, "get item: " + model.toString());
		return model;
	}

	private static OrderModel createOrderModel(JSONObject joTemp)
			throws JSONException {
		OrderModel model = new OrderModel();
		
		model.setId(joTemp.getInt(KEY_ID));
		model.setItemID(joTemp.getInt(KEY_ITEM_ID));
		model.setOrderTime(Utilities.getStringNotNull(joTemp.getString(KEY_ORDER_TIME).trim()));
		model.setOrderUser(Utilities.getStringNotNull(joTemp.getString(KEY_ORDER_USER)));
		model.setQuantity(joTemp.getInt(KEY_QUANTITY));
		model.setStatus(Utilities.getStringNotNull(joTemp.getString(KEY_STATUS).trim()));
		model.setTableNo(Integer.parseInt(joTemp.getString(KEY_TABLE_NO).trim()));
		String cm = Utilities.getStringNotNull(joTemp.getString(KEY_COMMENT));
		cm = URLDecoder.decode(cm);
		cm = (CommConstant.SIGN_NULL.equals(cm)) ? null : cm;
		model.setComment(cm);
		
		Log.i(tag, "loaded order: " + model.toString());
		return model;
	}
}
